import {defineConfig, loadEnv} from 'vite'
import vue from '@vitejs/plugin-vue'
import {resolve} from "path";
import {creatLocalProxy} from "./vite/proxy.ts";
import {visualizer} from "rollup-plugin-visualizer";
import viteCompression from 'vite-plugin-compression';
import {ViteImageOptimizer} from "vite-plugin-image-optimizer";

const CWD = process.cwd();

export default defineConfig(({command, mode, isSsrBuild, isPreview}) => {
    const env = loadEnv(mode, CWD)
    console.log("【环境变量】", env, '\n\n')
    let config = {
        base: env.VITE_BASE,
        cacheDir: './.vite_cache', // 指定持久化缓存目录
        server: {
            port: 9696,
            host: true,
            open: false,
            proxy: creatLocalProxy(),
        },
        resolve: {
            alias: {
                '@': resolve(__dirname, './src'),
                '@asset': resolve(__dirname, './src/asset'),
                '@component': resolve(__dirname, './src/component'),
                '@direct': resolve(__dirname, './src/direct'),
                '@enum': resolve(__dirname, './src/enum'),
                '@language': resolve(__dirname, './src/language'),
                '@layout': resolve(__dirname, './src/layout'),
                '@router': resolve(__dirname, './src/router'),
                '@store': resolve(__dirname, './src/store'),
                '@style': resolve(__dirname, './src/style'),
                '@type': resolve(__dirname, './src/type'),
                '@util': resolve(__dirname, './src/util'),
                '@view': resolve(__dirname, './src/view'),
            },
        },
        css: {
            preprocessorOptions: {
                scss: {
                    additionalData: `@import "@style/theme/theme.scss";`
                },
                less: {
                    additionalData: `@import "@style/theme/theme.less";`,
                    javascriptEnabled: true, // 若需Less中使用JS表达式（如Ant Design主题定制）
                }
            }
        },
        plugins: [
            vue(),
            // ✅ 打包体积分析
            visualizer({
                filename: '打包分析报告.html', // 输出文件名
                open: false, // 构建后自动打开浏览器报告
                gzipSize: true,   // 显示 Gzip 后体积
                // brotliSize: true, // 显示 Brotli 后体积
            })
        ],
        build: {
            outDir: env.VITE_BUILD_OUT_DIR,
        }
    }

    // 压缩打包
    if (command === 'build' && env.VITE_BUILD_OPEN_COMPRESS == 'true') {
        buildCompress(config, env)
        pluginCompress(config, env)
    }

    return config;
})

/**
 * ！生产环境优化打包
 *
 * 【压缩】
 * 优先项：代码压缩 + 图片优化 + 代码分割（覆盖 80% 优化需求）
 * 进阶项：预构建配置 + CDN外部化 + 多线程压缩（大型项目必备）
 * Nginx：压缩后，启用 gzip_static 或 brotli_static 才能生效
 *
 * 【一键配置】
 * npm install -D vite-plugin-compression terser rollup-plugin-visualizer sharp svgo vite-plugin-chunk-split
 *
 * vite-plugin-imagemin
 *
 * 【说明】
 * vite-plugin-compression //生成 Gzip/Brotli 格式的压缩文件（如 .gz 或 .br），减小静态资源体积
 * terser //代码压缩和混淆，支持移除 console、debugger 等调试语句
 * vite-plugin-image-optimizer、sharp、svgo //图像、SVG 优化
 * vite-plugin-chunk-split //分包优化插件，首屏加载速度提升 30%-50%
 * rollup-plugin-visualizer //生成构建产物可视化报告，分析模块体积和依赖关系
 * lodash-es（替代 lodash） //ESM 格式的 Lodash 库，支持 Tree Shaking 按需引入，减少打包体积
 * vite-plugin-cdn-import //将第三方库（如 Vue、Lodash）替换为 CDN 链接，减小构建体积
 * postcss + autoprefixer + cssnano //自动添加 CSS 前缀、压缩 CSS 代码
 *
 * 【nginx】
 * http {
 *   gzip_static on;    # 优先返回预生成的 .gz 文件
 *   brotli_static on;  # 优先返回预生成的 .br 文件
 *   # 动态压缩回退（可选）
 *   gzip on;
 *   brotli on;
 * }
 */
function pluginCompress(config: any, env: any) {
    config.plugins = [
        vue(),
        // ✅  Gzip
        viteCompression({
            algorithm: 'gzip',     // 可选 'gzip' 或 'brotli'
            ext: '.gz',            // 压缩后缀（gzip用.gz，brotli用.br）
            threshold: 10240,      // 仅压缩 >10KB 的文件（单位：字节）
            deleteOriginFile: true, // 删除原始文件
            verbose: true,         // 控制台输出压缩详情
            filter: /\.(js|css|html|json)$/i // 仅压缩文本文件，排除图片
        }),
        // ✅  Brotli 需要nginx额外安装内容
        // viteCompression({
        //     algorithm: 'brotliCompress',
        //     ext: '.br',
        //     threshold: 10240,
        //     deleteOriginFile: true,
        //     verbose: true,
        //     filter: /\.(js|css|html|json)$/i
        // }),
        // ✅ 图片压缩 TODO 进一步优化
        ViteImageOptimizer({
            png: {
                // 质量 80~90（低于 80 可能失真）
                quality: 85,
                // 压缩级别 0-9（9 为最高压缩）
                compressionLevel: 9,
                // 启用调色板优化（减少色深）
                palette: true,
                // Sharp 专用参数，优化压缩效率（默认 4，最高 10）
                effort: 10,
            },
            jpeg: {
                // 质量 70~85（推荐 80）
                quality: 80,
                //启用渐进式加载
                progressive: true,
                // ✅ 禁用色度抽样（避免色彩模糊）
                chromaSubsampling: '4:4:4',
            },
            jpg: {
                quality: 80,
                progressive: true,
            },
            webp: {
                quality: 85, // 提升至 85
                lossless: false, // 有损压缩
                effort: 6, // 保持最高压缩强度
                nearLossless: true, // ✅ 启用近无损模式（Sharp 专属）
            },
            avif: {
                // AVIF 压缩率更高，质量可略低
                quality: 75,
                lossless: false,
                effort: 9 // 提升压缩强度（默认 4，最高 9）
            },
            // ✅  SVG 配置（无需 active）
            svg: {
                //多次优化
                multipass: true,
                plugins: [
                    // 保留 viewBox（防止变形）
                    {name: 'removeViewBox'},
                    // 移除空属性
                    {name: 'removeEmptyAttrs'},
                    // 颜色转 currentColor
                    {name: 'convertColors', params: {currentColor: true}}
                ],
            },
            // 启用缓存（加速二次构建）
            cache: true,
            // 自定义缓存目录,绝对路径避免跨平台问题
            cacheLocation: resolve(__dirname, '.image-cache'),
            // 优化 public 目录下的图片
            includePublic: true,
            // 终端显示优化统计
            logStats: true,
            // 日志启用颜色
            ansiColors: true,
            // 匹配文件类型,内置 i 标志 不区分大小写
            test: /\.(png|jpe?g|gif|tiff|webp|avif|svg)$/i,
            // 匹配所有图片
            include: /\.(png|jpe?g|gif|tiff|webp|avif|svg)$/i,
            // include: /[\\/]src[\\/]asset[\\/].*?\.(?:png|jpe?g|gif|tiff|webp|avif|svg)$/i,
            // 排除 node_modules
            exclude: /node_modules|public\/fonts/,
        }),
        // ✅ 打包体积分析
        visualizer({
            filename: '打包分析报告.html', // 输出文件名
            open: false, // 构建后自动打开浏览器报告
            gzipSize: true,   // 显示 Gzip 后体积
            brotliSize: true, // 显示 Brotli 后体积
        })
    ]
}

function buildCompress(config: any, env: any) {
    config.build = {
        // 文件输出路径
        outDir: env.VITE_BUILD_OUT_DIR,
        // ✅ 大于 10KB 的资源保留为独立文件，小于则转为 Base64 内联
        assetsInlineLimit: 10 * 1024,
        // ✅ 代码压缩和混淆，支持移除 console、debugger 等调试语句
        minify: "terser",
        terserOptions: {
            compress: {
                drop_console: true,// 移除所有 console 语句
                drop_debugger: true,// 移除 debugger
                pure_funcs: ['console.log'], // 仅移除特定函数（如保留 console.error）
            },
            format: {
                comments: false,//删除注释（保留许可证需设为 'some'）
            },
            mangle: {
                properties: {
                    regex: /^_/,// 指定混淆：将 "_" 开头的私有属性混淆
                }
            }
        },
        // ✅ 代码分包 开启分包
        // 错误注意禁止循环依赖 util内使用api.xxx  api里面使用util.xxx ,这样不行
        rollupOptions: {
            output: {
                //1. 智能第三方依赖拆包
                manualChunks(id: any) {
                    if (id.includes('node_modules')) {
                        // 核心库独立分包（避免重复加载）
                        if (id.includes('vue') || id.includes('vue-router') || id.includes('pinia')) {
                            return 'vendor-core';
                        }
                        // 大体积库独立分包（如 Echarts > 500KB）
                        if (id.includes('echarts') || id.includes('xlsx')) {
                            return 'vendor-' + id.split('node_modules/')[1].split('/')[0];
                        }
                        // 其他依赖合并
                        return 'vendor';
                    }
                    //2. 业务代码按路由分包
                    if (id.includes('/src/view/')) {
                        const match = id.match(/\/src\/view\/(\w+)\//);
                        return match ? `route-${match[1]}` : null;
                    }

                    // ✅ 将高频互调模块合并到同一chunk
                    //  比如说： util.ts内使用api.xxx  api.ts里面使用util.xxx
                    // if (id.includes('util') || id.includes('api')) {
                    //     return 'chunk-core'; // 合并为同一chunk
                    // }

                },
                //3. 文件名哈希优化（长效缓存）
                chunkFileNames: 'js/[name]-[hash:8].js',
                entryFileNames: 'js/[name]-[hash:8].js',
                //4. 静态资源分类存储
                assetFileNames: 'asset/[ext]/[name]-[hash:8].[ext]'
            }
        }
    }
}

